#ifndef __TREE_H__
#define __TREE_H__

#include <utility>
#include <vector>

struct TreeNode
{
    TreeNode* left;
    TreeNode* right;
    int data;

    explicit TreeNode(const int value) : data(value), left(nullptr), right(nullptr) {}
};

void preOrder(const TreeNode* tree);

void inOrder(const TreeNode* tree);

void postOrder(const TreeNode* tree);

void reverseTree(TreeNode* tree);

TreeNode* createTreeForTest(const int arr[], const int n);

void deleteTree(TreeNode*& tree);

template <typename T>
class BinaryTree
{
  public:
    BinaryTree() = default;
    BinaryTree(const std::vector<T>& arr);
    ~BinaryTree() { clear(); }
    void createFromLevelOrder(const std::vector<T>& arr);

    bool insertLeft(const TreeNode* parent, const T& val);
    bool insertRight(const TreeNode* parent, const T& val);

    void deleteSubtree(TreeNode*& node);
    void upateValue(TreeNode* node, const T& newValue);

    TreeNode* leftChild(const TreeNode* node);
    TreeNode* leftRight(const TreeNode* node);

    size_t size() const;
    size_t depth() const;

    bool empty() const;

  private:
    void clear();
};

#endif  //__TREE_H__